Newsgroups: comp.sys.sgi.admin,comp.sys.sgi.bugs From: Steve Kotsopoulos <steve@ecf.toronto.edu> Date: Tue, 9 Aug 1994 09:44:19 -0400 I am cc'ing this update to several mailing lists the advisory has been forwarded to since last week. Likewise. ... : If we told you what the problem was, then you might go break into other : machines. That wouldn't look good for SGI. ... When the truth comes out, this *isn't* going to look good for SGI, period. This is an ugly bug. As the source at SGI wrote : It's such : a quiet little hole that it doesn't leave a mark anywhere. You don't : even have to logon to exploit it. That's how bad it is. ... Corrections and updates to the above information is encouraged. OK, here comes a big update [well, 1 and 2 are somewhat old news; 3 is the real news]. 1) The problem would allow even people who couldn't logon to become root. [As per the SGI source, above.] However, it could also be exploited in a slightly different way by those who had already logged on as normal users to become root. **** The SGI official patch of removing ViewerHelp only stops the non-logged in; normal users can still become root. **** 2) As I posted before, renaming /usr/sbin/sgihelp out of existance will stop both variants; however you lose all 'desktop help'. See below for a better option. 3) I enclose below a wrapper program for sgihelp that will stop both the logged-in and the non-logged-in variant without losing help. You mv /usr/sbin/sgihelp to /usr/sgihelp.real, and then install the compiled wrapper program as /usr/sbin/sgihelp. No guarantees, but it seems to do the trick. /* A security wrapper for sgihelp, written 8/9/94 by Max Hailperin <max@gac.edu>. Sets the effective uid and gid back to the real ones, unless that is 0 (root), in which case nobody is used instead. (See code for details.) Public domain, no warranty of any kind. */ /* configuration options: REAL_SGIHELP is the pathname of what used to be /usr/sbin/sgihelp [i.e., mv /usr/sbin/sgihelp to this path, then install this wrapper program as /usr/sbin/sghihelp] */ #define REAL_SGIHELP "/usr/sbin/sgihelp.real" /* BLOCK_HASH is the hashcode for a certain program from which sgihelp access should be disallowed; either it should be defined or sgihelp.books.ViewerHelp should be removed as SGI recommended. Otherwise, a security violation will still be possible (though not as severe a one as without this wrapper program). Either way you lose something; with BLOCK_HASH defined, there is no help available from that one program (though it is one very few people need help with). With ViewerHelp removed, you can't get help on the help viewer. Personally I prefer BLOCK_HASH as the lesser evil. */ #define BLOCK_HASH 636 #include <sys/types.h> #include <unistd.h> #include <limits.h> #ifdef BLOCK_HASH #include <sys/procfs.h> #include <fcntl.h> #include <stdio.h> #endif main(int argc, char *argv[], char *envp[]){ setgid(getgid()); setuid(getuid()); if(getuid() == 0){ /* if the real uid is 0 (root), then as a special case we setuid to -2 (nobody) rather that 0 because some setuid root programs once they have effective uid 0 then use that priviledge to set their real uid to 0 as well; thus a real uid of 0 may not mean that the real user is root, but possibly just that such a program is an ancestor; running as nobody is unlikely to cause many problems for real root users and protects against the kind of programs mentioned above. Since uids are mod UID_MAX+1, -2 => UID_MAX-1. */ setuid(UID_MAX-1); #ifdef BLOCK_HASH {int fd; char fname[256], *cp; unsigned hash = 0; struct prpsinfo info; sprintf(fname, "/proc/pinfo/%05d", getppid()); if((fd = open(fname, O_RDONLY)) < 0) exit(1); if(ioctl(fd, PIOCPSINFO, &info) < 0) exit(1); for(cp = info.pr_fname; *cp; cp++) hash += *cp; if(hash == BLOCK_HASH) exit(1); } #endif } execve(REAL_SGIHELP, argv, envp); exit(1); }